﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Web.Services.Protocols;
using Grain.Crm.Common;
using Grain.Crm.DataMigrator.Imports;
using System.Diagnostics;
using Grain.Crm.DataMigrator.CrmServices;
using Grain.Crm.DataMigrator.Infrastructure;
using Grain.Crm.DataMigrator.Properties;
using Grain.Crm.ExcelExtractor;
using Grain.Crm.ExcelExtractor.InputDescription;
using Grain.Crm.ExcelExtractor.InputDescription.Sheets;
using Grain.Crm.ExcelImporter.Serializer;
using Grain.Crm.ExcelProcessor;

namespace Grain.Crm.DataMigrator
{

    public class ImportsJob
    {
        static void Main(string[] args)
        {
            InitialSerializer.Serialize();

            try
            {
                

                Console.WriteLine("ExcelImporter v.2.0. \n");
                ProfileSheetDescription profileDesc;
                SkillsSheetDescription skillsDesc;

                SheetsManager.BuildDescriptions(out profileDesc, out skillsDesc);

                var payloads = new List<ImportPayload>();
                var serviceUrl = Settings.Default.Grain_Crm_DataMigrator_CrmServices_CrmService;
                var filename = Settings.Default.SheetFile;
                var org = Settings.Default.CrmOrganization;
                var user = Settings.Default.ServiceUser;
                var pwd = Settings.Default.ServicePassword;
                var domain = Settings.Default.Domain;
                ValueDescription.SheetCulture = Thread.CurrentThread.CurrentCulture.Name;
                ImportsGlobal.Language = Settings.Default.Lanuage;

                EnumerableRowCollection<DataRow> profileCollection, skillsCollection;

              
                var filePath = Path.Combine(Helper.AssemblyDirectory, filename);

                Console.WriteLine("Parsing sheet file '" + filePath + "'");
                XlsProcessor.QueryData(filePath, profileDesc.SheetName, out profileCollection);

                payloads.Add(ImportPayloadGenerator.GeneratePayload(profileDesc, profileCollection,
                                                                    EntityName.contact.ToString(), filename));
                payloads.Add(ImportPayloadGenerator.GeneratePayload(profileDesc, profileCollection,
                                                                    EntityName.new_curriculumvitae.ToString(), filename));
                payloads.Add(ImportPayloadGenerator.GeneratePayload(profileDesc, profileCollection,
                                                                    EntityName.new_contactlanguage.ToString(), filename));

             
                XlsProcessor.QueryData(filePath, skillsDesc.SheetName, out skillsCollection);

                payloads.Add(ImportPayloadGenerator.GeneratePayload(skillsDesc, skillsCollection,
                                                                    EntityName.new_contactskill.ToString(), filename));

                Console.WriteLine("\nParsing done.");

                var result = Run(serviceUrl, org, domain, user, pwd,
                                                     ImportsGlobal.Language, payloads);

                if (result.AllImportsSucceed)
                {
                    Console.ForegroundColor = ConsoleColor.Green;
                    Console.WriteLine("\n>> Finished. All imports succeed.");
                }
                else
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine("\n>> Finished. At least one import failed.");
                }

                Console.WriteLine("\n -- Press any key to exit --");
                Console.ReadLine();
            }
            catch(Exception ex)
            {
                Console.WriteLine("\nAn error has occured. \n\nMessage:\n" + ex.Message + "\n\nDetails:\n" + ex.ToString());

                Console.WriteLine("\nPress <enter> to exit..");
                Console.ReadLine();
            }
        }

        public static ImportsResult Run(string crmServerUrl, string orgName,
            string domain, string username, string password, string language, IEnumerable<ImportPayload> data)
        {
            #region Setup service


            Console.WriteLine("Starting import. Language:" + ImportsGlobal.Language);
            Console.WriteLine("Connecting to Crm service..");

            //http://195.12.133.178:6668/MSCRMServices/2007/CrmService.asmx
            CrmService service = CrmServiceUtility.GetCrmService(crmServerUrl, orgName, domain, username, password);

            Console.WriteLine("Connected.");


            WhoAmIRequest who = new WhoAmIRequest();

            Console.WriteLine("Retrieving crm user..");
            WhoAmIResponse whoResponse = (WhoAmIResponse)service.Execute(who);
            Console.WriteLine("Crm user retrieved: userID: " + whoResponse.UserId.ToString());
            #endregion

            var result = new ImportsResult();
            result.AllImportsSucceed = true;
            Exception ex;
            bool success = true;

            foreach (var dataItem in data)
            {
                var import = ImportFactory.Create(service, whoResponse, dataItem);

                success = import.Execute(out ex);

                if (ex != null) PrintException(ex);

                result.AllImportsSucceed &= success;
                if (ex != null)
                    result.Exceptions.Add(ex);

            }

            return result;
        }

        private static void PrintException(Exception ex)
        {
            Console.ForegroundColor = ConsoleColor.Red;

            var soapException = ex as SoapException;
            if (soapException != null)
            {
                Console.WriteLine("There was a Soap exception.");
                Console.WriteLine(soapException.Message);
                Console.WriteLine(soapException.Detail.InnerText);
            }
            else
            {
                Console.WriteLine("There was an application exception.");
                Console.WriteLine(ex.ToString());

                // Display the details of the inner exception.
                if (ex.InnerException != null)
                {
                    Console.WriteLine(ex.InnerException.Message);

                    SoapException se = ex.InnerException as SoapException;
                    if (se != null)
                        Console.WriteLine(se.Detail.InnerText);

                }
            }
            Console.ResetColor();
        }

    }

    public class InitialSerializer
    {
        public static void Serialize()
        {
            var importTask = new ImportEntityTask("new_curriculumvitae");
            importTask.SearchAttributes = new []
                                              {
                                                  new SearchAttribute("new_contactid", 
                                                      new CrmIdResolver("contact", new[] {"fullname"} , new[] { new SheetValueResolver("Contact") })),

                                                  new SearchAttribute("new_languageid",
                                                      new CrmIdResolver("new_language", new[] {"new_name"}, new[] {new SheetValueResolver("Language")})
                                                      ), 
                                              };

           DataSerializer<ImportEntityTask> dataSerializer = new DataSerializer<ImportEntityTask>();
            
           dataSerializer.Serialize(Helper.AssemblyDirectory + @"\cvImportTask.xml", importTask);

        }
    }
}
